package com.zhangsun.springShiro.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhangsun.springShiro.common.constant.Constant;
import com.zhangsun.springShiro.common.provider.RedisProvider;
import com.zhangsun.springShiro.framework.bcrypt.BCryptPasswordEncoder;
import com.zhangsun.springShiro.framework.expection.BusinessException;
import com.zhangsun.springShiro.framework.jwt.JwtTokenUtil;
import com.zhangsun.springShiro.system.bean.TheUser;
import com.zhangsun.springShiro.system.bean.UserEdit;
import com.zhangsun.springShiro.system.bean.UserResult;
import com.zhangsun.springShiro.system.entity.UserEntity;
import com.zhangsun.springShiro.system.mapper.UserMapper;
import com.zhangsun.springShiro.system.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * <p>
 * 用户 服务实现类
 * </p>
 *
 * @author zhangsun
 * @since 2019-07-23
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    /**
     * token参数名
     */
    @Value("${jwt.header}")
    private String header;

    /**
     * token前缀
     */
    @Value("${jwt.tokenType}")
    private String tokenType;

    @Autowired
    private RedisProvider redisProvider;

    @Transactional
    @Override
    public void createUser(UserEdit edit) {
        checkUserUnique(edit.getUserNo());

        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(edit, userEntity);
        userEntity.setPassword(new BCryptPasswordEncoder().encode(edit.getPassword()));
        userEntity.insert();
    }

    @Transactional
    @Override
    public void createAdmin() {
        checkUserUnique(Constant.ADMIN_USER_NO);

        UserEntity userEntity = new UserEntity();
        userEntity.setId(Constant.ADMIN_USER_ID);
        userEntity.setUserNo(Constant.ADMIN_USER_NO);
        userEntity.setName(Constant.ADMIN_USER_NO);
        userEntity.setMobile("18662910888");
        userEntity.setPassword(new BCryptPasswordEncoder().encode("123456"));
        userEntity.insert();
    }

    /**
     * 判断用户工号是否唯一
     *
     * @param userNo 用户工号
     */
    private void checkUserUnique(String userNo) {
        LambdaQueryWrapper<UserEntity> queryWrapper = new QueryWrapper<UserEntity>().lambda();
        queryWrapper.eq(UserEntity::getUserNo, userNo);
        int count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new BusinessException("该工号已存在");
        }
    }

    @Override
    public UserEntity findByUserNo(String userNo) {
        LambdaQueryWrapper<UserEntity> queryWrapper = new QueryWrapper<UserEntity>().lambda();
        queryWrapper.eq(UserEntity::getUserNo, userNo);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public UserResult login(String userNo, String password) {
        UserEntity userEntity = findByUserNo(userNo);
        if (userEntity == null) {
            throw new BusinessException("该用户不存在");
        }

        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        if (!bCryptPasswordEncoder.matches(password, userEntity.getPassword())) {
            throw new BusinessException("用户名或密码不正确");
        }

        UserResult userResult = new UserResult();
        userResult.setUserId(userEntity.getId());
        userResult.setUserNo(userEntity.getUserNo());
        userResult.setName(userEntity.getName());
        userResult.setMobile(userEntity.getMobile());
        userResult.setToken(jwtTokenUtil.generateToken(userEntity.getUserNo(), userEntity.getPassword()));
        return userResult;
    }

    @Override
    public void logout(HttpServletRequest request) {
        //用户退出逻辑
        Subject subject = SecurityUtils.getSubject();

        String authHeader = request.getHeader(header);
        String token = authHeader.substring(tokenType.length());
        //清空用户Token缓存
        redisProvider.del(token);

        //清空用户权限缓存：权限Perms和角色集合
        TheUser theUser = (TheUser) subject.getPrincipal();
        redisProvider.del(theUser.getUserId() + ":resource");
        redisProvider.del(theUser.getUserId() + ":role");
        subject.logout();
    }

    @Override
    public List<UserEntity> findAll() {
        LambdaQueryWrapper<UserEntity> queryWrapper = new QueryWrapper<UserEntity>().lambda();
        return baseMapper.selectList(queryWrapper);
    }
}
